TensorBoard Usage -- Updated

Looks like I need to relearn Tensorboard since my old code is all deprecated :/ Tutorial link: link

  1. Create the TensorFlow graph that you'd like to collect summary data from, and decide which nodes you would like to annotate with summary operations.

    def variable_summaries(var):
    """Attach a lot of summaries to a Tensor (for TensorBoard visualization)."""
    with tf.name_scope('summaries'):
     mean = tf.reduce_mean(var)
     tf.summary.scalar('mean', mean)
     with tf.name_scope('stddev'):
       stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
     tf.summary.scalar('stddev', stddev)
     tf.summary.scalar('max', tf.reduce_max(var))
     tf.summary.scalar('min', tf.reduce_min(var))
     tf.summary.histogram('histogram', var)
    
  2. To generate summaries, we need to run all of these summary nodes. Combine them into a single op that generates all the summary data.

    merged = tf.summary.merge_all()
    
  3. Run the merged summary op, which will generate a serialized Summary protobuf object with all of your summary data at a given step. Finally, to write this summary data to disk, pass the summary protobuf to a tf.summary.FileWriter.

    train_writer = tf.summary.FileWriter(FLAGS.summaries_dir + '/train',
                                       sess.graph)
    test_writer = tf.summary.FileWriter(FLAGS.summaries_dir + '/test')
    tf.global_variables_initializer().run()
    
  4. During training . . .

    summary, acc = sess.run([merged, accuracy], feed_dict=feed_dict(False))
     test_writer.add_summary(summary, i)
    
  5. Launching tensorboard after training.

    tensorboard --logdir=path/to/log-directory

Description of below code (docstring):

A simple MNIST classifier which displays summaries in TensorBoard. This is an unimpressive MNIST model, but it is a good example of using tf.name_scope to make a graph legible in the TensorBoard graph explorer, and of naming summary tags so that they are grouped meaningfully in TensorBoard. It demonstrates the functionality of every TensorBoard dashboard.


In [ ]:
import argparse
import sys
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

In [ ]:
def train():
    mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)

    sess = tf.InteractiveSession()
    # Create a multilayer model.

    # Input placeholders
    with tf.name_scope('input'):
        x = tf.placeholder(tf.float32, [None, 784], name='x-input')
        y_ = tf.placeholder(tf.float32, [None, 10], name='y-input')

    with tf.name_scope('input_reshape'):
        image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
        tf.summary.image('input', image_shaped_input, 10)

    # We can't initialize these variables to 0 - the network will get stuck.
    def weight_variable(shape):
        """Create a weight variable with appropriate initialization."""
        initial = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(initial)

    def bias_variable(shape):
        """Create a bias variable with appropriate initialization."""
        initial = tf.constant(0.1, shape=shape)
        return tf.Variable(initial)

    def variable_summaries(var):
        """Attach a lot of summaries to a Tensor (for TensorBoard visualization)."""
        with tf.name_scope('summaries'):
            mean = tf.reduce_mean(var)
            tf.summary.scalar('mean', mean)
            with tf.name_scope('stddev'):
                stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
            tf.summary.scalar('stddev', stddev)
            tf.summary.scalar('max', tf.reduce_max(var))
            tf.summary.scalar('min', tf.reduce_min(var))
            tf.summary.histogram('histogram', var)

    def nn_layer(input_tensor, input_dim, output_dim, layer_name, act=tf.nn.relu):
        """Reusable code for making a simple neural net layer.

        It does a matrix multiply, bias add, and then uses relu to nonlinearize.
        It also sets up name scoping so that the resultant graph is easy to read,
        and adds a number of summary ops.
        """
        # Adding a name scope ensures logical grouping of the layers in the graph.
        with tf.name_scope(layer_name):
            # This Variable will hold the state of the weights for the layer
            with tf.name_scope('weights'):
                weights = weight_variable([input_dim, output_dim])
                variable_summaries(weights)
            with tf.name_scope('biases'):
                biases = bias_variable([output_dim])
                variable_summaries(biases)
            with tf.name_scope('Wx_plus_b'):
                preactivate = tf.matmul(input_tensor, weights) + biases
                tf.summary.histogram('pre_activations', preactivate)
            activations = act(preactivate, name='activation')
            tf.summary.histogram('activations', activations)
            return activations

    hidden1 = nn_layer(x, 784, 500, 'layer1')

    with tf.name_scope('dropout'):
        keep_prob = tf.placeholder(tf.float32)
        tf.summary.scalar('dropout_keep_probability', keep_prob)
        dropped = tf.nn.dropout(hidden1, keep_prob)

    # Do not apply softmax activation yet, see below.
    y = nn_layer(dropped, 500, 10, 'layer2', act=tf.identity)

    with tf.name_scope('cross_entropy'):
        # The raw formulation of cross-entropy,
        #
        # tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.softmax(y)),
        #                               reduction_indices=[1]))
        #
        # can be numerically unstable.
        #
        # So here we use tf.nn.softmax_cross_entropy_with_logits on the
        # raw outputs of the nn_layer above, and then average across
        # the batch.
        diff = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)
        with tf.name_scope('total'):
            cross_entropy = tf.reduce_mean(diff)
    tf.summary.scalar('cross_entropy', cross_entropy)

    with tf.name_scope('train'):
        train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize(cross_entropy)

    with tf.name_scope('accuracy'):
        with tf.name_scope('correct_prediction'):
            correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        with tf.name_scope('accuracy'):
            accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar('accuracy', accuracy)

    # Merge all the summaries and write them out to /tmp/tensorflow/mnist/logs/mnist_with_summaries (by default)
    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter(FLAGS.log_dir + '/train', sess.graph)
    test_writer = tf.summary.FileWriter(FLAGS.log_dir + '/test')
    tf.global_variables_initializer().run()

    # Train the model, and also write summaries.
    # Every 10th step, measure test-set accuracy, and write test summaries
    # All other steps, run train_step on training data, & add training summaries

    def feed_dict(train):
        """Make a TensorFlow feed_dict: maps data onto Tensor placeholders."""
        if train or FLAGS.fake_data:
            xs, ys = mnist.train.next_batch(100, fake_data=FLAGS.fake_data)
            k = FLAGS.dropout
        else:
            xs, ys = mnist.test.images, mnist.test.labels
            k = 1.0
        return {x: xs, y_: ys, keep_prob: k}

    for i in range(FLAGS.max_steps):
        if i % 10 == 0:  # Record summaries and test-set accuracy
            summary, acc = sess.run([merged, accuracy], feed_dict=feed_dict(False))
            test_writer.add_summary(summary, i)
            print('Accuracy at step %s: %s' % (i, acc))
        else:  # Record train set summaries, and train
            if i % 100 == 99:  # Record execution stats
                run_options = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
                run_metadata = tf.RunMetadata()
                summary, _ = sess.run([merged, train_step],
                                      feed_dict=feed_dict(True),
                                      options=run_options,
                                      run_metadata=run_metadata)
                train_writer.add_run_metadata(run_metadata, 'step%03d' % i)
                train_writer.add_summary(summary, i)
                print('Adding run metadata for', i)
            else:  # Record a summary
                summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
                train_writer.add_summary(summary, i)
    train_writer.close()
    test_writer.close()

In [ ]:
def main(_):
    if tf.gfile.Exists(FLAGS.log_dir):
        tf.gfile.DeleteRecursively(FLAGS.log_dir)
    tf.gfile.MakeDirs(FLAGS.log_dir)
    train()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--fake_data', nargs='?', const=True, type=bool,
              default=False,
              help='If true, uses fake data for unit testing.')
    parser.add_argument('--max_steps', type=int, default=1000,
              help='Number of steps to run trainer.')
    parser.add_argument('--learning_rate', type=float, default=0.001,
              help='Initial learning rate')
    parser.add_argument('--dropout', type=float, default=0.9,
              help='Keep probability for training dropout.')
    parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
    parser.add_argument('--log_dir', type=str, default='/tmp/tensorflow/mnist/logs/mnist_with_summaries',help='Summaries log directory')
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

Trying to save the Graph Again

Tutorial Link

In order for a Python object to be serialized to and from MetaGraphDef, the Python class must implement to_proto() and from_proto() methods, and register them with the system using register_proto_function:


In [ ]:
class Variable:

    def to_proto(self, export_scope=None):
        """Converts a `Variable` to a `VariableDef` protocol buffer.

        Args:
        export_scope: Optional `string`. Name scope to remove.

        Returns:
        A `VariableDef` protocol buffer, or `None` if the `Variable` is not
        in the specified name scope.
        """
        if (export_scope is None or self._variable.name.startswith(export_scope)):
            var_def                  = variable_pb2.VariableDef()
            var_def.variable_name    = ops.strip_name_scope(self._variable.name, export_scope)
            var_def.initializer_name = ops.strip_name_scope(self.initializer.name, export_scope)
            var_def.snapshot_name    = ops.strip_name_scope(self._snapshot.name, export_scope)
            if self._save_slice_info:
                var_def.save_slice_info_def.MergeFrom(self._save_slice_info.to_proto(export_scope=export_scope))
            return var_def
        else:
            return None

    @staticmethod
    def from_proto(variable_def, import_scope=None):
        """Returns a `Variable` object created from `variable_def`."""
        return Variable(variable_def=variable_def, import_scope=import_scope)


ops.register_proto_function(ops.GraphKeys.GLOBAL_VARIABLES,
                            proto_type=variable_pb2.VariableDef,
                            to_proto=Variable.to_proto,
                            from_proto=Variable.from_proto)

Exporting a MetaGraph

The function signature, for reference:

def export_meta_graph(filename=None, collection_list=None, as_text=False):
  """Writes `MetaGraphDef` to save_path/filename.

  Args:
    filename: Optional meta_graph filename including the path.
    collection_list: List of string keys to collect.
    as_text: If `True`, writes the meta_graph as an ASCII proto.

  Returns:
    A `MetaGraphDef` proto.
  """

You should store all variables you wanna get letter in collection. Or, if you don't specify one, it will save everything (yeah do that).

How to export the default running graph:


In [ ]:
logits = tf.matmul(hidden2, weights) + biases
tf.add_to_collection("logits", logits)

init_all_op = tf.global_variables_initializer()

with tf.Session() as sess:
    # Initializes all the variables.
    sess.run(init_all_op)
    # Runs to logit.
    sess.run(logits)
    chatbot.saver.save(sess, 'my-save-dir/my-model-10000')
    # Generates MetaGraphDef.
    chatbot.saver.export_meta_graph('my-save-dir/my-model-10000.meta')

Importing the MetaGraph and Resuming Training

Case: Import and Extend Graph


In [ ]:
with tf.Session() as sess:
    new_saver = tf.train.import_meta_graph('my-save-dir/my-model-10000.meta')
    new_saver.restore(sess, 'my-save-dir/my-model-10000')
    
    # Adds loss and train.
    labels = tf.constant(0, tf.int32, shape=[100], name="labels")
    batch_size = tf.size(labels)
    labels = tf.expand_dims(labels, 1)
    indices = tf.expand_dims(tf.range(0, batch_size), 1)
    concated = tf.concat([indices, labels], 1)
    onehot_labels = tf.sparse_to_dense(concated, tf.stack([batch_size, 10]), 1.0, 0.0)
    
    # Getting the logits variable back that we saved.
    logits = tf.get_collection("logits")[0]
    cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=onehot_labels, logits=logits, name="xentropy")
    loss = tf.reduce_mean(cross_entropy, name="xentropy_mean")

    tf.summary.scalar('loss', loss)
    # Creates the gradient descent optimizer with the given learning rate.
    optimizer = tf.train.GradientDescentOptimizer(0.01)

    # Runs train_op.
    train_op = optimizer.minimize(loss)
    sess.run(train_op)

Case: Retrieve Hyperparameters


In [ ]:
filename = ".".join([tf.latest_checkpoint(train_dir), "meta"])
tf.train.import_meta_graph(filename)
hparams = tf.get_collection("hparams")

Sharing Variables

My version of TensorFlow's tutorial by the same name, but in English. The (sub)section names are identical; I compress the content.

The Problem

Reusing the same model on multiple inputs: Let's say we make a function my_model(inputs) that creates a bunch of tf.Variable() objects and returns the final output tensor variable. Each time we call my_model(next_inputs), it is going to create a whole new model with new variables. This bad.

How to fix?: Rather than requiring classes to create a model and manage the variables, TensorFlow provides a Variable scope mechanism for sharing named variables while constructing a graph.

Variable Scope

The mechanism consists of 2 main functions:

  1. tf.get_variable(name, shape, initializer) creates or returns a variable with a given name.
  2. tf.variable_scope(scope_name) manages namespaces for names passed to tf.get_variable().

Difference between name scope and variable scope: Here is a link to the best explanation I could find. The following is the main part:

"However, name scope is ignored by tf.get_variable. We can see that in the following example:

with tf.name_scope("my_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32)
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)

print(v1.name)  # var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

The only way to place a variable accessed using tf.get_variable in a scope is to use variable scope, as in the following example:

with tf.variable_scope("my_scope"):
    v1 = tf.get_variable("var1", [1], dtype=tf.float32)
    v2 = tf.Variable(1, name="var2", dtype=tf.float32)
    a = tf.add(v1, v2)

print(v1.name)  # my_scope/var1:0
print(v2.name)  # my_scope/var2:0
print(a.name)   # my_scope/Add:0

RNN Documentation

RNNCell

Interface Specifications

It's extremely helpful to read the source code for RNNCell. Let's see a condensed list of the important methods and descriptions.

  • __call__: Run this RNN cell on inputs, starting from the given state.
def __call__(self, inputs, state, scope=None):
  """Args:
      inputs: `2-D` tensor with shape `[batch_size x input_size]`.
      state: if `self.state_size` is an integer, this should be a `2-D Tensor`
        with shape `[batch_size x self.state_size]`.  Otherwise, if
        `self.state_size` is a tuple of integers, this should be a tuple
        with shapes `[batch_size x s] for s in self.state_size`.
      scope: VariableScope for the created subgraph; defaults to class name.
    Returns:
      A pair containing:
      - Output: A `2-D` tensor with shape `[batch_size x self.output_size]`.
      - New state: Either a single `2-D` tensor, or a tuple of tensors matching
        the arity and shapes of `state`.
    """
  • state_size and output_size:
@property
  def state_size(self):
    """size(s) of state(s) used by this cell.
    It can be represented by an Integer, a TensorShape or a tuple of Integers
    or TensorShapes.
    """

  @property
  def output_size(self):
    """Integer or TensorShape: size of outputs produced by this cell."""
  • zero_state:
    def zero_state(self, batch_size, dtype):
      """Return zero-filled state tensor(s).
      Args:
        batch_size: int, float, or unit Tensor representing the batch size.
        dtype: the data type to use for the state.
      Returns:
        If `state_size` is an int or TensorShape, then the return value is a
        `N-D` tensor of shape `[batch_size x state_size]` filled with zeros.
        If `state_size` is a nested list or tuple, then the return value is
        a nested list or tuple (of the same structure) of `2-D` tensors with
        the shapes `[batch_size x s]` for each s in `state_size`.
      """
      with ops.name_scope(type(self).__name__ + "ZeroState", values=[batch_size]):
        state_size = self.state_size
        return _zero_state_tensors(state_size, batch_size, dtype)
    

Decoder Class -- Currently undocumented . . .

Here I'm going to give myself an overview of this strange new set of files in tf.contrib.seq2seq (master branch) that is not on the website.

Basic Decoder

Miscellaneous

Review: logits terminology

  1. Logistic function: $$\begin{align} p(X) &= \frac{1}{1 + e^{-\beta^TX}} \\ &= \frac{e^{ \beta^TX}}{1 + e^{ \beta^TX}} \end{align}$$

  2. Odds: $$ \frac{p(X)}{1 - p(X)} = e^{\beta^T X} $$

  3. log-odds, "logit": $$ \log\left(\frac{p(X)}{1 - p(X)} \right) = \beta^T X $$

Random Facts

  • tf.Variable vs tf.placeholder: "The difference is that with tf.Variable you have to provide an initial value when you declare it. With tf.placeholder you don't have to provide an initial value and you can specify it at run time with the feed_dict argument inside Session.run" Source

Embedding Lookup

Goal: Figure out how embedding lookup works. Ideally i'd like to show, as a toy example, an integer being mapped to its binary string. For example, with embed size of 5

embed([2, 19]) --> [[0, 0, 0, 1, 0], [1, 0, 0, 1, 1]]

In [ ]:
import tensorflow as tf
import numpy as np

input_size = (1, 2) # arbitrary
embed_size = 5
vocab_size = 2**embed_size
input_array = np.random.randint(vocab_size, size=input_size)
expected_embedding = ['{0:b}'.format(inp) for inp in input_array.flatten()]
print("Input array:\n", input_array)
print("Expected embedding:\n", expected_embedding)

In [15]:
tf.reset_default_graph()
sess = None
with tf.Session() as sess:
    params   = tf.get_variable('embed_tensor', 
                               shape=[vocab_size, embed_size], 
                               initializer=tf.contrib.layers.xavier_initializer())
    inputs    = tf.convert_to_tensor(input_array)
    embedding = tf.nn.embedding_lookup(params, inputs)
    
    
    sess.run(tf.global_variables_initializer())
    emb = sess.run(embedding)
    print(emb)

sess = None
tf.reset_default_graph()


[[[ 0.30149388 -0.099668    0.14693063 -0.39335564  0.34846574]
  [-0.0505532  -0.21680753 -0.3851763  -0.1110653   0.0726169 ]]]

Embedding Visualizer


In [1]:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys 
import os
import numpy as np
from tensorflow.contrib.tensorboard.plugins import projector
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
FLAGS = None

In [ ]:
def generate_embeddings():
    # Import data
    mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True, fake_data=FLAGS.fake_data)
    sess = tf.InteractiveSession()
    # Input set for Embedded TensorBoard visualization
    # Performed with cpu to conserve memory and processing power
    with tf.device("/cpu:0"):
        embedding = tf.Variable(tf.stack(mnist.test.images[:FLAGS.max_steps], axis=0), 
                                trainable=False, name='embedding')
    tf.global_variables_initializer().run()
    saver = tf.train.Saver()
    writer = tf.summary.FileWriter(FLAGS.log_dir + '/projector', sess.graph)
    # Add embedding tensorboard visualization. 
    config = projector.ProjectorConfig()
    embed= config.embeddings.add()
    embed.tensor_name = 'embedding:0'
    embed.metadata_path = os.path.join(FLAGS.log_dir + '/projector/metadata.tsv')
    embed.sprite.image_path = os.path.join(FLAGS.data_dir + '/mnist_10k_sprite.png')
    # Specify the width and height of a single thumbnail.
    embed.sprite.single_image_dim.extend([28, 28])
    projector.visualize_embeddings(writer, config)
    saver.save(sess, os.path.join(
        FLAGS.log_dir, 'projector/a_model.ckpt'), global_step=FLAGS.max_steps)

def generate_metadata_file():
    # Import data
    mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True, fake_data=FLAGS.fake_data)
    def save_metadata(file):
        with open(file, 'w') as f:
            for i in range(FLAGS.max_steps):
                c = np.nonzero(mnist.test.labels[::1])[1:][0][i]
                f.write('{}\n'.format(c))
    save_metadata(FLAGS.log_dir + '/projector/metadata.tsv')

In [ ]:
def main(_):
    if tf.gfile.Exists(FLAGS.log_dir + '/projector'):
        tf.gfile.DeleteRecursively(FLAGS.log_dir + '/projector')
        tf.gfile.MkDir(FLAGS.log_dir + '/projector')
    tf.gfile.MakeDirs(FLAGS.log_dir  + '/projector') # fix the directory to be created
    generate_metadata_file()
    generate_embeddings()

if __name__ == '__main__':
    BASE = '/home/brandon/mnist-tensorboard-embeddings/'
    parser = argparse.ArgumentParser()
    parser.add_argument('--fake_data', nargs='?', const=True, type=bool,
                        default=False, help='If true, uses fake data for unit testing.')
    parser.add_argument('--max_steps', type=int, default=10000, help='Number of steps to run trainer.')
    parser.add_argument('--data_dir', type=str, default=BASE+'mnist_data', help='Directory for storing input data')
    parser.add_argument('--log_dir', type=str, default=BASE+'logs', help='Summaries log directory')
    FLAGS, unparsed = parser.parse_known_args()
    tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

YES: TensorBoard Summit Tutorial Code


In [4]:
import os
import tensorflow as tf
import urllib
import urllib.request

LOGDIR = '/tmp/mnist_tutorial/'
GIST_URL = 'https://gist.githubusercontent.com/dandelionmane/4f02ab8f1451e276fea1f165a20336f1/raw/                            dfb8ee95b010480d56a73f324aca480b3820c180'

### MNIST EMBEDDINGS ###
mnist = tf.contrib.learn.datasets.mnist.read_data_sets(train_dir=LOGDIR + 'data', one_hot=True)
### Get a sprite and labels file for the embedding projector ###
urllib.request.urlretrieve(GIST_URL + 'labels_1024.tsv', LOGDIR + 'labels_1024.tsv')
urllib.request.urlretrieve(GIST_URL + 'sprite_1024.png', LOGDIR + 'sprite_1024.png')


Extracting /tmp/mnist_tutorial/data/train-images-idx3-ubyte.gz
Extracting /tmp/mnist_tutorial/data/train-labels-idx1-ubyte.gz
Extracting /tmp/mnist_tutorial/data/t10k-images-idx3-ubyte.gz
Extracting /tmp/mnist_tutorial/data/t10k-labels-idx1-ubyte.gz
Out[4]:
('/tmp/mnist_tutorial/sprite_1024.png',
 <http.client.HTTPMessage at 0x7f59ff6014e0>)

In [5]:
def conv_layer(input, size_in, size_out, name="conv"):
    with tf.name_scope(name):
        w = tf.Variable(tf.truncated_normal([5, 5, size_in, size_out], stddev=0.1), name="W")
        b = tf.Variable(tf.constant(0.1, shape=[size_out]), name="B")
        conv = tf.nn.conv2d(input, w, strides=[1, 1, 1, 1], padding="SAME")
        act = tf.nn.relu(conv + b)
        tf.summary.histogram("weights", w)
        tf.summary.histogram("biases", b)
        tf.summary.histogram("activations", act)
        return tf.nn.max_pool(act, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
    
def fc_layer(input, size_in, size_out, name="fc"):
    with tf.name_scope(name):
        w = tf.Variable(tf.truncated_normal([size_in, size_out], stddev=0.1), name="W")
        b = tf.Variable(tf.constant(0.1, shape=[size_out]), name="B")
        act = tf.nn.relu(tf.matmul(input, w) + b)
        tf.summary.histogram("weights", w)
        tf.summary.histogram("biases", b)
        tf.summary.histogram("activations", act)
        return act

In [6]:
def mnist_model(learning_rate, use_two_conv, use_two_fc, hparam):
    tf.reset_default_graph()
    sess = tf.Session()
    # Setup placeholders, and reshape the data
    x = tf.placeholder(tf.float32, shape=[None, 784], name="x")
    x_image = tf.reshape(x, [-1, 28, 28, 1]) 
    tf.summary.image('input', x_image, 3)
    y = tf.placeholder(tf.float32, shape=[None, 10], name="labels")
    if use_two_conv:
        conv1 = conv_layer(x_image, 1, 32, "conv1")
        conv_out = conv_layer(conv1, 32, 64, "conv2")
    else:
        conv1 = conv_layer(x_image, 1, 64, "conv")
        conv_out = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
    flattened = tf.reshape(conv_out, [-1, 7 * 7 * 64])
    if use_two_fc:
        fc1 = fc_layer(flattened, 7 * 7 * 64, 1024, "fc1")
        embedding_input = fc1 
        embedding_size = 1024
        logits = fc_layer(fc1, 1024, 10, "fc2")
    else:
        embedding_input = flattened
        embedding_size = 7*7*64
        logits = fc_layer(flattened, 7*7*64, 10, "fc")
    with tf.name_scope("xent"):
        xent = tf.reduce_mean(
        tf.nn.softmax_cross_entropy_with_logits(
            logits=logits, labels=y), name="xent")
        tf.summary.scalar("xent", xent)
    with tf.name_scope("train"):
        train_step = tf.train.AdamOptimizer(learning_rate).minimize(xent)
    with tf.name_scope("accuracy"):
        correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1)) 
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        tf.summary.scalar("accuracy", accuracy)
    summ = tf.summary.merge_all()
    
    # _________ EMBEDDING VARIABLE/TENSOR CREATED _________
    embedding = tf.Variable(tf.zeros([1024, embedding_size]), name="test_embedding")
    assignment = embedding.assign(embedding_input)
    
    # _________ SAVER CREATED _________
    saver = tf.train.Saver()
    
    # _________ INIT GLOBAL VARS IS RUN  _________
    sess.run(tf.global_variables_initializer())
    
    # _________ WRITER IS CREATED  _________
    writer = tf.summary.FileWriter(LOGDIR + hparam)
    writer.add_graph(sess.graph)
    
    # ================================================================
    # _________ PROJECTORCONFIG CONSTRUCTOR  _________
    config = tf.contrib.tensorboard.plugins.projector.ProjectorConfig()
    embedding_config = config.embeddings.add()
    embedding_config.tensor_name = embedding.name
    embedding_config.sprite.image_path = LOGDIR + 'sprite_1024.png'
    embedding_config.metadata_path = LOGDIR + 'labels_1024.tsv'
    # Specify the width and height of a single thumbnail.
    embedding_config.sprite.single_image_dim.extend([28, 28])
    tf.contrib.tensorboard.plugins.projector.visualize_embeddings(writer, config)
    # ================================================================
    
    for i in range(2001):
        batch = mnist.train.next_batch(100)
        if i % 5 == 0:
            [train_accuracy, s] = sess.run([accuracy, summ], feed_dict={x: batch[0], y: batch[1]})
            writer.add_summary(s, i)
        if i % 500 == 0:
            sess.run(assignment, feed_dict={x: mnist.test.images[:1024], y: mnist.test.labels[:1024]})
            saver.save(sess, os.path.join(LOGDIR, "model.ckpt"), i)
        sess.run(train_step, feed_dict={x: batch[0], y: batch[1]})

In [8]:
def make_hparam_string(learning_rate, use_two_fc, use_two_conv):
    conv_param = "conv=2" if use_two_conv else "conv=1"
    fc_param = "fc=2" if use_two_fc else "fc=1"
    return "lr_%.0E,%s,%s" % (learning_rate, conv_param, fc_param)

def main():
    # You can try adding some more learning rates
    for learning_rate in [1E-4]:
        # Include "False" as a value to try different model architectures
        for use_two_fc in [True]:
            for use_two_conv in [True]:
                # Construct a hyperparameter string for each one (example: "lr_1E-3,fc=2,conv=2)
                hparam = make_hparam_string(learning_rate, use_two_fc, use_two_conv)
                print('Starting run for %s' % hparam)

                # Actually run with the new settings
                mnist_model(learning_rate, use_two_fc, use_two_conv, hparam)

Misc. Ops Testing

tf concat with -1 as an argument? No documentation on it so guess we'll have to try it out.


In [ ]:
import tensorflow as tf
import numpy as np

a = tf.convert_to_tensor(np.arange(20).reshape(5, 4))
concat = tf.concat([[-1, 1], tf.shape(a)], 0)

In [7]:
# Config (hopefully) fixes GPU not releasing memory issue in jupyter.
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
with tf.Session(config=config) as sess:
    print(sess.run(concat))


[-1  1  5  4]

In [ ]:


In [ ]: